home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / (A)G / (A)G2.ADF / Othello / CSOthello.c < prev    next >
C/C++ Source or Header  |  1988-12-01  |  44KB  |  1,893 lines

  1. #include <exec/types.h>
  2. #include <lattice/stdio.h>
  3. #include <intuition/intuition.h>
  4.  
  5. #define VERSION       1
  6.  
  7. #define MAXBOXES        12
  8. #define MAXLOOK         10
  9. #define WIDE        64 * 2
  10. #define HIGH           512
  11. #define LINEHEIGHT      10
  12. #define XBORDER          6
  13. #define YBORDER          3
  14. #define BOXIT         TRUE
  15. #define NOBOXIT      FALSE
  16. #define IDCMPNORMAL CLOSEWINDOW | MENUPICK | MOUSEBUTTONS
  17.  
  18. #define DISKDEFNAME      "Othello.def"
  19.  
  20. #include <othmenu.h>
  21.  
  22. #define EMPTY            0
  23. #define BLACK            1
  24. #define RED              2
  25. #define OFFSCREEN        3
  26.  
  27. #define DEFAULTP1        HUMAN
  28. #define DEFAULTP2        HUMAN
  29. #define DEFAULTSIZE      8
  30. #define DEFAULTGURUWAIT  STEPTHROUGH
  31.  
  32. struct Image logo =
  33.    {
  34.    0, 0,
  35.    POINTERWIDTH * 2, POINTERHEIGHT, 2,
  36.    NULL,
  37.    3, 0,
  38.    NULL
  39.    };
  40.  
  41. USHORT ourpointerdata[] =
  42.    {
  43.    0x0000, 0x0000,
  44.  
  45.    0x0000, 0x3000,
  46.    0x0000, 0x4800,
  47.    0x0000, 0x4000,
  48.    0x0080, 0x4000,
  49.    0x0080, 0x4000,
  50.    0x02A0, 0x4800,
  51.    0x01C0, 0x3000,
  52.    0x0080, 0x0000,
  53.    0x1004, 0x1004,
  54.    0x0808, 0x0808,
  55.    0x7C1F, 0x7C9F,
  56.    0x0808, 0x0808,
  57.    0x1004, 0x1004,
  58.    0x0080, 0x0000,
  59.    0x01C0, 0x0006,
  60.    0x02A0, 0x0009,
  61.    0x0080, 0x0008,
  62.    0x0080, 0x0006,
  63.    0x0000, 0x0001,
  64.    0x0000, 0x0009,
  65.    0x0000, 0x0006,
  66.  
  67.    0x0000, 0x0000
  68.    };
  69.  
  70. USHORT *ourpointer = 0;
  71. ULONG  *ourlongpointer;
  72. ULONG  expand();
  73.  
  74. extern struct Menu Titles[];
  75. extern struct MenuItem Items[];
  76. extern struct MenuItem SubItems[];
  77.  
  78. struct IntuitionBase *IntuitionBase = NULL;
  79. struct GfxBase       *GfxBase = NULL;
  80. struct Window *window = NULL;
  81. unsigned char  *circle = NULL;
  82.  
  83. struct IntuiMessage   *message;
  84. char  gamebuffer[MAXLOOK][MAXBOXES+2][MAXBOXES+2];
  85. char  *game[MAXLOOK][MAXBOXES+2];
  86.  
  87. short looksp1, looksp2;
  88. short whoseturn;
  89. short guruwait;
  90. BOOL  workbench;
  91. short whostarts = BLACK;
  92.  
  93. ULONG class;
  94. short xoffset, yoffset, ytextoff;
  95. short xthought, ythought;
  96. short scores[3];
  97. short width, height;
  98. short numboxes, boxheight, boxwidth;
  99. BOOL  stuck, newgame;
  100.  
  101. char bonus[MAXBOXES+2][MAXBOXES+2];
  102.  
  103. struct IntuiText Quittext =
  104.    {
  105.       2,1,
  106.       JAM2,
  107.       23,10,
  108.       NULL,
  109.       " Really Quit?",
  110.       NULL
  111.    };
  112.  
  113. struct IntuiText Postext =
  114.    {
  115.       2,1,
  116.       JAM2,
  117.       6,3,
  118.       NULL,
  119.       "Yes",
  120.       NULL
  121.    };
  122.  
  123. struct IntuiText Negtext =
  124.    {
  125.       2,1,
  126.       JAM2,
  127.       6,3,
  128.       NULL,
  129.       "No Way!",
  130.       NULL
  131.    };
  132.  
  133. struct Image textplayer =
  134. {
  135.    0, 0,             /* leftedge, topedge     */
  136.    16, 8, 1,          /* width, height, depth  */
  137.    NULL,             /* image data pointer    */
  138.    1, 0,             /* planepick, planeonoff */
  139.    NULL              /* next image            */
  140. };
  141.  
  142. struct Image player =
  143. {
  144.    5, 2,             /* leftedge, topedge     */
  145.    0, 0, 1,          /* width, height, depth  */
  146.    NULL,             /* image data pointer    */
  147.    1, 0,             /* planepick, planeonoff */
  148.    NULL              /* next image            */
  149. };
  150.  
  151. UBYTE *yourmove = "Your move, player   .            ";
  152. UBYTE *cantmove = "Player    can't move.            ";
  153. UBYTE *victory  = "Player    wins.                  ";
  154. UBYTE *tiegame  = "The game is a tie.               ";
  155. UBYTE *finished = "Game over.                       ";
  156. UBYTE *neither  = "Neither player can move.         ";
  157. UBYTE *scoreis  = "                                 ";
  158. UBYTE *notempty = "That square is already taken.    ";
  159. UBYTE *notlegal = "That is not a legal move.        ";
  160. UBYTE *bestmove = "This is your best move.          ";
  161. UBYTE *youcant  = "You can't move.                  ";
  162. UBYTE *possible = "These are all the possible moves.";
  163. UBYTE *blank    = "                                 ";
  164. UBYTE *thinking = "Please wait - I'm thinking.      ";
  165. UBYTE *click    = "Click in window to continue.     ";
  166. UBYTE *openfail = "File could not be opened.        ";
  167. UBYTE *illvalue = "Illegal value in file.           ";
  168. UBYTE *shortfil = "Invalid data file.  Too short.   ";
  169. UBYTE *loaded   = "Game loaded.                     ";
  170. UBYTE *saved    = "Game saved.                      ";
  171. UBYTE *writfail = "Write to file failed.            ";
  172. UBYTE *defsaved = "Defaults saved.                  ";
  173.  
  174. ULONG powers[32];
  175.  
  176. struct TextAttr smallfont =
  177. {
  178.    "Topaz80",8,0,0
  179. };
  180.  
  181. struct IntuiText string =
  182. {
  183.    1, 0,             /* frontpen, backpen */
  184.    JAM2,             /* drawmode          */
  185.    0,0,              /* leftedge, topedge */
  186.    &smallfont,       /* pointer to font   */
  187.    NULL,             /* pointer to text data */
  188.    NULL              /* next text */
  189. };
  190.  
  191. short squarepoints[10];
  192. short smallsquarepoints[10];
  193.  
  194. struct Border square =
  195. {
  196.    0, 0,             /* leftedge, topedge */
  197.    2, 0, JAM1,       /* frontpen, backpen, drawmode */
  198.    5,                /* count */
  199.    squarepoints,     /* xy data */
  200.    NULL              /* next border */
  201. };
  202.  
  203. struct Border smallsquare =
  204. {
  205.    0, 0,             /* leftedge, topedge */
  206.    1, 0, JAM1,       /* frontpen, backpen, drawmode */
  207.    5,                /* count */
  208.    smallsquarepoints, /* xy data */
  209.    NULL              /* next border */
  210. };
  211.  
  212. struct Border xline =
  213. {
  214.    0, 0,             /* leftedge, topedge */
  215.    3, 0, JAM1,       /* frontpen, backpen, drawmode */
  216.    2,                /* count */
  217.    squarepoints,     /* xy data */
  218.    NULL              /* next border */
  219. };
  220.  
  221. struct Border yline =
  222. {
  223.    0, 0,             /* leftedge, topedge */
  224.    3, 0, JAM1,       /* frontpen, backpen, drawmode */
  225.    2,                /* count */
  226.    squarepoints + 6, /* xy data */
  227.    NULL              /* next border */
  228. };
  229.  
  230. struct NewWindow newwindow =
  231. {
  232.    0,0,
  233.    330,185,
  234.    -1,-1,
  235.    IDCMPNORMAL,
  236.    WINDOWDEPTH | WINDOWDRAG | WINDOWCLOSE | SMART_REFRESH | ACTIVATE,
  237.    NULL,
  238.    NULL,
  239.    "CSOthello - ⌐ CygnusSoft.",
  240.    NULL,
  241.    NULL,
  242.    330,185,
  243.    330,185,
  244.    WBENCHSCREEN
  245. };
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252. main(argc,argv)
  253. int argc;
  254. char *argv[];
  255. {
  256. short  r, x, y, level;
  257.  
  258.    powers[0] = 1;
  259.    for (x = 1; x < 32; x++)
  260.       powers[x] = powers[x-1] * 2;
  261.  
  262.    workbench = (argc == 0);
  263.  
  264.    if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 29)))
  265.       quit_cleanup("Can't open Intuition Library.");
  266.  
  267.    if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",29)))
  268.       quit_cleanup("Can't open Graphics library.");
  269.  
  270.    if (!(window = (struct Window *)OpenWindow(&newwindow)))
  271.       quit_cleanup("Can't open the window.");
  272.  
  273.    xoffset = window->BorderLeft + XBORDER;
  274.    ytextoff = window->BorderTop + YBORDER;
  275.    yoffset = ytextoff + 3 * LINEHEIGHT + YBORDER;
  276.    width = window->Width - xoffset - window->BorderRight - XBORDER;
  277.    height = window->Height - yoffset - window->BorderBottom - YBORDER;
  278.  
  279.    string.LeftEdge = xoffset;
  280.    string.TopEdge = ytextoff;
  281.  
  282.    getdefaults();    /* must be called before set menu strip,
  283.                         but after assigning xoffset, ytextoff */
  284.  
  285.    SetMenuStrip(window, Titles);
  286.  
  287.    if (ourpointer = (USHORT *)AllocRaster(POINTERWIDTH*2,POINTERHEIGHT*2))
  288.       {
  289.       ourlongpointer = (ULONG *)ourpointer;
  290.       for (y = 0; y < POINTERHEIGHT; y++)
  291.          {
  292.          ourlongpointer[y] = expand(ourpointerdata[y * 2 + 2]);
  293. /*         ourpointer[y] = ourpointerdata[y * 2 + 2];
  294.          ourpointer[y + POINTERHEIGHT] = ourpointerdata[y * 2 + 3];   */
  295.          ourlongpointer[y + POINTERHEIGHT] = expand(ourpointerdata[y * 2 + 3]);
  296.          }
  297.       logo.ImageData = ourpointer;
  298.       DrawImage(window->RPort, &logo, xoffset + width - 32, ytextoff);
  299.       for (y = 0; y < (POINTERHEIGHT + 2) * 2; y++)
  300.          ourpointer[y] = ourpointerdata[y];
  301.       SetPointer(window,ourpointer,POINTERHEIGHT,POINTERWIDTH,POINTERXOFF,POINTERYOFF);
  302.       }
  303.  
  304.    if (!(circle = (unsigned char *)AllocRaster(WIDE, HIGH)))
  305.       quit_cleanup("Can't allocate raster data.");
  306.  
  307.    for (r = 4; r <= 4; r++)
  308.       generatecircle(r, circle + (r-1)*256);
  309.    textplayer.ImageData = (short *)&circle[256 * 3];
  310.  
  311.    for (level = 0; level < MAXLOOK; level++)
  312.       for (x = 0; x < MAXBOXES + 2; x++)
  313.          game[level][x] = gamebuffer[level][x];
  314.  
  315.    initialize();
  316.  
  317.    info(PROJECT, ABOUT, NULL);
  318.  
  319.    while (TRUE)
  320.    {
  321.       showplayer(whoseturn, 141, 0);
  322.       if (moveable(whoseturn))   /* the player can move */
  323.       {
  324.          stuck = FALSE;
  325.          if (whoseturn == BLACK)
  326.             domoveblack();
  327.          else domovered();
  328.       }
  329.       else if (stuck == TRUE)    /* neither player can move */
  330.          endgame();
  331.       else                       /* one, maybe two, players can move */
  332.       {
  333.          printstring(cantmove, 0, LINEHEIGHT);
  334.          showplayer(whoseturn, 52, LINEHEIGHT);
  335.          stuck = TRUE;
  336.          whoseturn = BLACK + RED - whoseturn;  /*must be done before wait*/
  337.          if (whoseturn == BLACK && looksp1 == HUMAN && looksp2 != HUMAN)
  338.             waitforclick(FALSE,FALSE);
  339.          else if (whoseturn == RED && looksp1 != HUMAN && looksp2 == HUMAN)
  340.             waitforclick(FALSE,FALSE);
  341.          else if (looksp1 != HUMAN && looksp1 != HUMAN && guruwait == STEPTHROUGH)
  342.             waitforclick(TRUE,FALSE);
  343.       }
  344.    }
  345. }
  346.  
  347.  
  348.  
  349. ULONG expand(word)
  350. short word;
  351. {
  352. short bit;
  353. ULONG answer;
  354.  
  355.    answer = 0;
  356.    for (bit = 0; bit < 16; bit++)
  357.       if (powers[bit] & word)
  358.          answer |= (powers[bit * 2] * 3);
  359.    return(answer);
  360. }
  361.  
  362.  
  363.  
  364. showplayer(current, x, y)
  365. short current, x, y;
  366. {
  367.    textplayer.PlanePick = current;
  368.    DrawImage(window->RPort, &textplayer, xoffset + x, ytextoff + y);
  369. }
  370.  
  371.  
  372.  
  373. generatecircle(r, p)
  374. short r;
  375. unsigned char *p;
  376. {
  377.    short x, y, rsquared, wordwidth;
  378.    short tx, ty;
  379.  
  380.    for (x = 0; x < 8 * 32; x++)
  381.       p[x] = 0;
  382.  
  383.    rsquared = r * r * 4 + 2;
  384.    wordwidth = (((r * 4) + 15) / 16) * 2;
  385.  
  386.    for (x = 0; x < r * 2; x++)
  387.       for (y = 0; y < r; y++)
  388.          if ((x * x + y * y * 4) < rsquared)
  389.          {
  390.             ty = r + y;
  391.             tx = 2 * r + x;
  392.             p[ty * wordwidth + (tx / 8)] |= powers[7 - (tx & 7)];
  393.             ty = r - y - 1;
  394.             p[ty * wordwidth + (tx / 8)] |= powers[7 - (tx & 7)];
  395.             tx = 2 * r - x - 1;
  396.             ty = r + y;
  397.             p[ty * wordwidth + (tx / 8)] |= powers[7 - (tx & 7)];
  398.             ty = r - y - 1;
  399.             p[ty * wordwidth + (tx / 8)] |= powers[7 - (tx & 7)];
  400.          }
  401. }
  402.  
  403. /*  for debug purposes only
  404.  
  405. printarray(index)
  406. short index;
  407. {
  408. short x, y;
  409.  
  410.    for (y = 0; y <= numboxes + 1; y++)
  411.    {
  412.       for (x = 0; x <= numboxes + 1; x++)
  413.          printf("%d ", game[index][x][y]);
  414.       printf("\n");
  415.    }
  416. }                          */
  417.  
  418.  
  419.  
  420. printscores()
  421. {
  422.    sprintf(scoreis, "Score:     %3d      %3d", scores[BLACK], scores[RED]);
  423.    printstring(scoreis, 0, LINEHEIGHT * 2);
  424.    showplayer(BLACK, 68, LINEHEIGHT * 2);
  425.    showplayer(RED, 140, LINEHEIGHT * 2);
  426. }
  427.  
  428.  
  429.  
  430. endgame()
  431. {
  432.    printstring(blank, 0, LINEHEIGHT);
  433.    if (scores[RED] + scores[BLACK] < numboxes * numboxes)
  434.       printstring(neither, 0, 0);
  435.    else
  436.       printstring(finished, 0, 0);
  437.    if (scores[BLACK] > scores[RED])
  438.    {
  439.       printstring(victory, 0, LINEHEIGHT);
  440.       showplayer(BLACK, 52, LINEHEIGHT);
  441.    }
  442.    else if (scores[BLACK] < scores[RED])
  443.    {
  444.       printstring(victory, 0, LINEHEIGHT);
  445.       showplayer(RED, 52, LINEHEIGHT);
  446.    }
  447.    else
  448.       printstring(tiegame, 0, LINEHEIGHT);
  449.  
  450.    newgame = FALSE;
  451.    while (TRUE)
  452.    {
  453.       WaitPort(window->UserPort);
  454.       message = (struct IntuiMessage *)GetMsg(window->UserPort);
  455.       processmessage();
  456.       if (newgame)
  457.          return(0);
  458.    }
  459. }
  460.  
  461.  
  462.  
  463. think(level, colour, index)
  464. short  level, colour, index;
  465. {
  466. short bestx = 0, besty = 0;
  467. short x, y, count = 0;
  468. int   best = -2000, temp;
  469. BOOL moved = FALSE;
  470.  
  471.    if (level == 0)
  472.    {
  473.       for ( x = 1; x <= numboxes; x++ )
  474.          for ( y = 1; y <= numboxes; y++ )
  475.            if (game[index][x][y] == EMPTY)
  476.                {
  477.                temp = move_i(x, y, colour, index);
  478.                if (temp > best)
  479.                   {
  480.                   best = temp;
  481.                   bestx = x;
  482.                   besty = y;
  483.                   }
  484.                else if (temp == best && index == MAXLOOK-1 )
  485.                   {
  486.                   count++;
  487.                   if (!(rand() % count))
  488.                      {
  489.                      best = temp;
  490.                      bestx = x;
  491.                      besty = y;
  492.                      }
  493.                   }
  494.                }
  495.       if (index == MAXLOOK - 1)  /* if first level then */
  496.       {
  497.          xthought = bestx;
  498.          ythought = besty;
  499.       }
  500.       return(best);
  501.    }
  502.    for ( x = 1; x <= numboxes; x++ )
  503.       for ( y = 1; y <= numboxes; y++ )
  504.          if (game[index][x][y] == EMPTY)
  505.             {
  506.             temp = move_i(x, y, colour, index);
  507.             if (temp > 0)
  508.                {
  509.                moved = TRUE;
  510.                copyplot(index, x, y, colour);
  511.                temp = temp - think(level-1, RED + BLACK - colour, index-1);
  512.                if (temp > best)
  513.                   {
  514.                   best = temp;
  515.                   bestx = x;
  516.                   besty = y;
  517.                   count = 1;
  518.                   }
  519.                else if (temp == best && index == MAXLOOK-1 )
  520.                   {
  521.                   count++;
  522.                   if (!(rand() % count))
  523.                      {
  524.                      best = temp;
  525.                      bestx = x;
  526.                      besty = y;
  527.                      }
  528.                   }
  529.                }
  530.             }
  531.    if (!(moved))    /* if colour cannot make a move then */
  532.    {
  533.       copy(index);
  534.       best = -think(level-1, RED + BLACK - colour, index - 1);
  535.    }
  536.    if (index == MAXLOOK - 1)  /* if first level then */
  537.    {
  538.       xthought = bestx;
  539.       ythought = besty;
  540.    }
  541.    return(best);
  542. }
  543.  
  544.  
  545.  
  546. dumbthink(level, colour, index)
  547. short  level, colour, index;
  548. {
  549. short x, y, count = 0;
  550. int   worst = 4000, temp;   /* the initial value of worst must be greater
  551.                      than the absolute value of the initial value of best
  552.                      in think in order to avoid deadlock on the last few
  553.                      moves.  */
  554.  
  555. /* this routine finds the worst move possible.  Since it is always called as
  556. the first level ( then it calls think() ) many checks can be dispensed with.
  557. We know there must be a move because otherwise this routine would not have
  558. been called. */
  559.  
  560.  
  561.    if (level == 0)
  562.    {
  563.       for ( x = 1; x <= numboxes; x++ )
  564.          for ( y = 1; y <= numboxes; y++ )
  565.            if (game[index][x][y] == EMPTY)
  566.                {
  567.                temp = move_i(x, y, colour, index);
  568.                if (temp)
  569.                   if (temp < worst)
  570.                      {
  571.                      worst = temp;
  572.                      xthought = x;
  573.                      ythought = y;
  574.                      }
  575.                   else if (temp == worst)
  576.                      {
  577.                      count++;
  578.                      if (!(rand() % count))
  579.                         {
  580.                         worst = temp;
  581.                         xthought = x;
  582.                         ythought = y;
  583.                         }
  584.                      }
  585.                }
  586.       return(worst);
  587.    }
  588.    for ( x = 1; x <= numboxes; x++ )
  589.       for ( y = 1; y <= numboxes; y++ )
  590.          if (game[index][x][y] == EMPTY)
  591.             {
  592.             temp = move_i(x, y, colour, index);
  593.             if (temp > 0)
  594.                {
  595.                copyplot(index, x, y, colour);
  596.                temp = temp - think(level-1, RED + BLACK - colour, index-1);
  597.                if (temp < worst)
  598.                   {
  599.                   worst = temp;
  600.                   xthought = x;
  601.                   ythought = y;
  602.                   count = 1;
  603.                   }
  604.                else if (temp == worst)
  605.                   {
  606.                   count++;
  607.                   if (!(rand() % count))
  608.                      {
  609.                      worst = temp;
  610.                      xthought = x;
  611.                      ythought = y;
  612.                      }
  613.                   }
  614.                }
  615.             }
  616.    return(worst);
  617. }
  618.  
  619.  
  620.  
  621. copyplot(index, x, y, colour)
  622. short index, x, y, colour;
  623. {
  624. short opponent;
  625. int   count;
  626. short count2, dx, dy, xcopy, ycopy, i;
  627.  
  628.    opponent = BLACK + RED - colour;
  629.  
  630.    copy(index);
  631.  
  632.    count = 0;
  633.  
  634.    if (game[index-1][x][y] != EMPTY)
  635.       quit_cleanup("Error.  Can't plot in filled box.");
  636.  
  637.    for (dx = -1; dx <= 1; dx++)
  638.       for (dy = -1; dy <= 1; dy++)
  639.       {
  640.          xcopy = x + dx;
  641.          ycopy = y + dy;
  642.          count2 = 0;
  643.          while ( game[index-1][xcopy][ycopy] == opponent )
  644.          {
  645.             count2++;
  646.             xcopy = xcopy + dx;
  647.             ycopy = ycopy + dy;
  648.          }
  649.          if (game[index-1][xcopy][ycopy] == colour)
  650.          {
  651.             count = count + count2;
  652.             for ( i = 1; i <= count2; i++)
  653.             {
  654.                xcopy = xcopy - dx;
  655.                ycopy = ycopy - dy;
  656.                game[index-1][xcopy][ycopy] = colour;
  657.             }
  658.          }
  659.       }
  660.    if (count)
  661.       game[index-1][x][y] = colour;
  662.    else
  663.       quit_cleanup("Error.  Illegal move by think.");
  664. }
  665.  
  666.  
  667.  
  668. copy(index)
  669. short index;
  670. {
  671. short dx, dy;
  672.  
  673.    for ( dx = 1; dx <= numboxes; dx++ )
  674.       for ( dy = 1; dy <= numboxes; dy++ )
  675.          game[index-1][dx][dy] = game[index][dx][dy];
  676. }
  677.  
  678.  
  679.  
  680. waitforclick(resume,printit)
  681. BOOL resume;    /* whether or not to resume if mode change to RACETHROUGH */
  682. BOOL printit;   /* whether or not to print click message */
  683. {
  684. struct IntuiMessage *message;
  685.  
  686.    if (scores[RED] + scores[BLACK] >= numboxes * numboxes)
  687.       return(0);
  688.    if (printit)
  689.       printstring(click, 0, LINEHEIGHT);
  690.    newgame = FALSE;
  691.    while (TRUE)
  692.    {
  693.       clearport();
  694.       WaitPort(window->UserPort);
  695.       message = (struct IntuiMessage *)GetMsg(window->UserPort);
  696.       if ( message->Class == MOUSEBUTTONS && message->Code == SELECTDOWN )
  697.       {
  698.          ReplyMsg(message);
  699.          return(0);
  700.       }
  701.       else
  702.          processmessage();
  703.       if ((guruwait == RACETHROUGH && resume) || newgame)
  704.          return(0);
  705.    }
  706. }
  707.  
  708.  
  709.  
  710. domovered()
  711. {
  712. short x, y;
  713. USHORT code;
  714.  
  715.    if (looksp2 != HUMAN)
  716.    {
  717.       printstring(thinking, 0, LINEHEIGHT);
  718.       if (looksp2 < LEVELM1)
  719.          think(looksp2, RED, MAXLOOK-1);
  720.       else
  721.          dumbthink(looksp2-LEVELM1, RED, MAXLOOK-1);
  722.       flip(xthought, ythought, RED);
  723.       clearport();
  724.       if (guruwait == STEPTHROUGH && looksp1 != HUMAN)
  725.          {
  726.          showplayer(whoseturn, 141, 0);
  727.          waitforclick(TRUE,TRUE);
  728.          }
  729.    }
  730.    else
  731.    {
  732.       WaitPort(window->UserPort);
  733.       message = (struct IntuiMessage *)GetMsg(window->UserPort);
  734.       if (message->Class == MOUSEBUTTONS)
  735.       {
  736.          x = message->MouseX;
  737.          y = message->MouseY;
  738.          code = message->Code;
  739.          ReplyMsg(message);
  740.          mouseclick(RED, x, y, code);
  741.       }
  742.       else
  743.          processmessage();
  744.    }
  745. }
  746.  
  747.  
  748.  
  749. domoveblack()
  750. {
  751. short x, y;
  752. USHORT code;
  753.  
  754.    if (looksp1 != HUMAN)
  755.    {
  756.       printstring(thinking, 0, LINEHEIGHT);
  757.       if (looksp1 < LEVELM1)
  758.          think(looksp1, BLACK, MAXLOOK-1);
  759.       else
  760.          dumbthink(looksp1-LEVELM1, BLACK, MAXLOOK-1);
  761.       flip(xthought, ythought, BLACK);
  762.       clearport();
  763.       if (guruwait == STEPTHROUGH && looksp2 != HUMAN)
  764.          {
  765.          showplayer(whoseturn, 141, 0);
  766.          waitforclick(TRUE,TRUE);
  767.          }
  768.    }
  769.    else
  770.    {
  771.       WaitPort(window->UserPort);
  772.       message = (struct IntuiMessage *)GetMsg(window->UserPort);
  773.       if (message->Class == MOUSEBUTTONS)
  774.       {
  775.          x = message->MouseX;
  776.          y = message->MouseY;
  777.          code = message->Code;
  778.          ReplyMsg(message);
  779.          mouseclick(BLACK, x, y, code);
  780.       }
  781.       else
  782.          processmessage();
  783.    }
  784. }
  785.  
  786.  
  787.  
  788. mouseclick(current, x, y, code)
  789. short  current, x, y;
  790. USHORT code;
  791. {
  792. struct IntuiMessage *message;
  793. short nx, ny;
  794.  
  795.    if (code != SELECTDOWN)
  796.       return(0);
  797.    nx = x - xoffset;
  798.    ny = y - yoffset;
  799.    x = nx / boxwidth;
  800.    y = ny / boxheight;
  801.    while (code != SELECTUP)
  802.    {
  803.       WaitPort(window->UserPort);
  804.       message = (struct IntuiMessage *)GetMsg(window->UserPort);
  805.       code = message->Code;
  806.       nx = message->MouseX - xoffset;
  807.       ny = message->MouseY - yoffset;
  808.       ReplyMsg(message);
  809.    }
  810.    if (x != (nx / boxwidth))
  811.       return(0);
  812.    if (y != (ny / boxheight))
  813.       return(0);
  814.    if (nx < 0 || ny < 0 || x >= numboxes || y >= numboxes)
  815.       return(0);
  816.    return(flip(x+1,y+1,current));
  817. }
  818.  
  819.  
  820.  
  821. flip(x,y,current)
  822. short x, y, current;
  823. {
  824. int   count;
  825. short count2, dx, dy, xcopy, ycopy, i;
  826. short opponent;
  827.  
  828.    printstring(blank, 0 ,LINEHEIGHT);
  829.  
  830.    opponent = RED + BLACK - current;
  831.  
  832.    count = 0;
  833.  
  834.    if (game[MAXLOOK-1][x][y] != EMPTY)
  835.    {
  836.       printstring(notempty, 0, LINEHEIGHT);
  837.       return(0);
  838.    }
  839.  
  840.    for (dx = -1; dx <= 1; dx++)
  841.       for (dy = -1; dy <= 1; dy++)
  842.       {
  843.          xcopy = x + dx;
  844.          ycopy = y + dy;
  845.          count2 = 0;
  846.          while ( game[MAXLOOK-1][xcopy][ycopy] == opponent )
  847.          {
  848.             count2++;
  849.             xcopy = xcopy + dx;
  850.             ycopy = ycopy + dy;
  851.          }
  852.          if (game[MAXLOOK-1][xcopy][ycopy] == current)
  853.          {
  854.             count = count + count2;
  855.             for ( i = 1; i <= count2; i++)
  856.             {
  857.                xcopy = xcopy - dx;
  858.                ycopy = ycopy - dy;
  859.                plot(xcopy,ycopy,current,NOBOXIT);
  860.             }
  861.          }
  862.       }
  863.    if (count)
  864.    {
  865.       scores[current] = scores[current] + count + 1;
  866.       scores[opponent] = scores[opponent] - count;
  867.       plot(x,y,current,BOXIT);
  868.       whoseturn = RED + BLACK - whoseturn;
  869.       printscores();
  870.    }
  871.    else
  872.       printstring(notlegal, 0, LINEHEIGHT);
  873.    return(count);
  874. }
  875.  
  876.  
  877.  
  878. moveable(current)
  879. {
  880. int   moves;
  881. short x, y;
  882.  
  883.    moves = 0;
  884.    for ( x = 1; x <= numboxes; x++)
  885.       for (y = 1; y <= numboxes; y++)
  886.          moves = moves + move(x,y,current,MAXLOOK-1);
  887.    return(moves);
  888. }
  889.  
  890.  
  891.  
  892. move(x,y,current,index)
  893. short x, y, current, index;
  894. {
  895. int   count;
  896. short count2, dx, dy, xcopy, ycopy, opponent;
  897.  
  898.    opponent = RED + BLACK - current;
  899.  
  900.    count = 0;
  901.  
  902.    if (game[index][x][y] != EMPTY)
  903.       return(0);
  904.  
  905.    for (dx = -1; dx <= 1; dx++)
  906.       for (dy = -1; dy <= 1; dy++)
  907.       {
  908.          xcopy = x + dx;
  909.          ycopy = y + dy;
  910.          count2 = 0;
  911.          while ( game[index][xcopy][ycopy] == opponent )
  912.          {
  913.             count2++;
  914.             xcopy = xcopy + dx;
  915.             ycopy = ycopy + dy;
  916.          }
  917.          if (game[index][xcopy][ycopy] == current)
  918.             count = count + count2;
  919.       }
  920.    return(count);
  921. }
  922.  
  923.  
  924.  
  925. move_i(x,y,current,index)
  926. short x, y, current, index;
  927. {
  928. REGISTER unsigned long count, count2, opponent;
  929. REGISTER char     *p, *p2;
  930.  
  931.    opponent = RED + BLACK - current;
  932.  
  933.    count = 0;
  934.  
  935.    p = &game[index][x][y];
  936.  
  937. /* We now look in each of the eight directions and find out how many (if
  938. any) pieces we can flip over.  I use pointers to directly access the members
  939. of the array and I have separate code for each direction for efficiency
  940. reasons.  I'm only going to comment the first of the eight because the
  941. comments for the others would be almost identical.  The original code, using
  942. nested for loops to look in all eight directions is shown at the bottom. */
  943.  
  944. /* check in the -x, -y direction */
  945.    p2 = p - (MAXBOXES+2 + 1); /* subtract 1 from x and y coordinates. */
  946.    if (*p2 == opponent)       /* is neighbouring piece opponents? */
  947.       {
  948.       count2 = 1;             /* set temporary flipped piece counter. */
  949.       p2 -= MAXBOXES+2 + 1;   /* subtract 1 from x and y coordinates. */
  950.       while (*p2 == opponent) /* go to end of row of opponents. */
  951.          {
  952.          count2++;            /* count the number of pieces passed over. */
  953.          p2 -=  MAXBOXES+2 + 1;  /* subtract 1 from x and y coordinate. */
  954.          }
  955.       if (*p2 == current)     /* if own piece ends line then, */
  956.          count += count2;     /* we can flip count pieces. */
  957.       }
  958.  
  959. /* check in the -y direction */
  960.    p2 = p - 1;
  961.    if (*p2 == opponent)
  962.       {
  963.       count2 = 1;
  964.       p2--;
  965.       while (*p2 == opponent)
  966.          {
  967.          count2++;
  968.          p2--;
  969.          }
  970.       if (*p2 == current)
  971.          count += count2;
  972.       }
  973.  
  974. /* check in the +x, -y direction */
  975.    p2 = p + (MAXBOXES+2) - 1;
  976.    if (*p2 == opponent)
  977.       {
  978.       count2 = 1;
  979.       p2 += MAXBOXES+2 - 1;
  980.       while (*p2 == opponent)
  981.          {
  982.          count2++;
  983.          p2 += MAXBOXES+2 - 1;
  984.          }
  985.       if (*p2 == current)
  986.          count += count2;
  987.       }
  988.  
  989. /* check in the -x direction */
  990.    p2 = p - (MAXBOXES+2);
  991.    if (*p2 == opponent)
  992.       {
  993.       count2 = 1;
  994.       p2 -= MAXBOXES+2;
  995.       while (*p2 == opponent)
  996.          {
  997.          count2++;
  998.          p2 -= MAXBOXES+2;
  999.          }
  1000.       if (*p2 == current)
  1001.          count += count2;
  1002.       }
  1003.  
  1004. /* check in the +x direction */
  1005.    p2 = p + MAXBOXES+2;
  1006.    if (*p2 == opponent)
  1007.       {
  1008.       count2 = 1;
  1009.       p2 += MAXBOXES+2;
  1010.       while (*p2 == opponent)
  1011.          {
  1012.          count2++;
  1013.          p2 += MAXBOXES+2;
  1014.          }
  1015.       if (*p2 == current)
  1016.          count += count2;
  1017.       }
  1018.  
  1019. /* check in the -x, +y direction */
  1020.    p2 = p + 1 - (MAXBOXES+2);
  1021.    if (*p2 == opponent)
  1022.       {
  1023.       count2 = 1;
  1024.       p2 += 1 - (MAXBOXES+2);
  1025.       while (*p2 == opponent)
  1026.          {
  1027.          count2++;
  1028.          p2 += 1 - (MAXBOXES+2);
  1029.          }
  1030.       if (*p2 == current)
  1031.          count += count2;
  1032.       }
  1033.  
  1034. /* check in the +y direction */
  1035.    p2 = p + 1;
  1036.    if (*p2 == opponent)
  1037.       {
  1038.       count2 = 1;
  1039.       p2++;
  1040.       while (*p2 == opponent)
  1041.          {
  1042.          count2++;
  1043.          p2++;
  1044.          }
  1045.       if (*p2 == current)
  1046.          count += count2;
  1047.       }
  1048.  
  1049. /* check in the +x, +y direction */
  1050.    p2 = p + MAXBOXES+2 + 1;
  1051.    if (*p2 == opponent)
  1052.       {
  1053.       count2 = 1;
  1054.       p2 += MAXBOXES+2 + 1;
  1055.       while (*p2 == opponent)
  1056.          {
  1057.          count2++;
  1058.          p2 += MAXBOXES+2 + 1;
  1059.          }
  1060.       if (*p2 == current)
  1061.          count += count2;
  1062.       }
  1063.  
  1064. /* This is the older, easier to read, but slower, move_i routine
  1065.    for (dx = -1; dx <= 1; dx++)
  1066.       for (dy = -1; dy <= 1; dy++)
  1067.       {
  1068.          xcopy = x + dx;
  1069.          ycopy = y + dy;
  1070.          count2 = 0;
  1071.          while ( game[index][xcopy][ycopy] == opponent )
  1072.          {
  1073.             count2++;
  1074.             xcopy = xcopy + dx;
  1075.             ycopy = ycopy + dy;
  1076.          }
  1077.          if (game[index][xcopy][ycopy] == current)
  1078.             count = count + count2;
  1079.       }          */
  1080.  
  1081.    if (count)
  1082.       return(count + bonus[x][y]);
  1083.    else
  1084.       return(0);
  1085. }
  1086.  
  1087.  
  1088.  
  1089. plot(x,y,current,box)
  1090. short x, y, current;
  1091. BOOL  box;
  1092. {
  1093.    if ( x < 1 || x > numboxes || y < 1 || y > numboxes)
  1094.       quit_cleanup("Illegal x or y value in plot call");
  1095.    drawboard();
  1096.    player.PlanePick = current;
  1097.    game[MAXLOOK-1][x][y] = current;
  1098.    if (box)
  1099.       highlight(x, y);
  1100.    x = xoffset + (x-1) * boxwidth;
  1101.    y = yoffset + (y-1) * boxheight;
  1102.    DrawImage(window->RPort, &player, x, y);
  1103. }
  1104.  
  1105.  
  1106.  
  1107. printstring(text, x, y)
  1108. char    *text;
  1109. short    x, y;
  1110. {
  1111.    string.IText = text;
  1112.    PrintIText(window->RPort, &string, x, y);
  1113. }
  1114.  
  1115.  
  1116.  
  1117. processmessage()
  1118. {
  1119. int    menucode;
  1120. long   class;
  1121. struct MenuItem *item;
  1122.  
  1123.    class = message->Class;
  1124.    menucode = message->Code;
  1125.    ReplyMsg(message);
  1126.    switch (class)
  1127.    {
  1128.       case CLOSEWINDOW :
  1129.          ClearMenuStrip(window);
  1130.          ModifyIDCMP(window,NULL);
  1131.          if ( AutoRequest(window,&Quittext,&Postext,&Negtext,
  1132.                         NULL,NULL,180,57) )
  1133.             {
  1134.             SetMenuStrip(window,Titles);
  1135.             quit_cleanup(0);
  1136.             }
  1137.          ModifyIDCMP(window,IDCMPNORMAL);
  1138.          SetMenuStrip(window,Titles);
  1139.          break;
  1140.       case MENUPICK :
  1141.          while (menucode != MENUNULL)
  1142.          {
  1143.             item = (struct MenuItem *)ItemAddress(Titles, menucode);
  1144.             processmenu(MENUNUM(menucode), ITEMNUM(menucode), SUBNUM(menucode));
  1145.             menucode = item->NextSelect;
  1146.          }
  1147.          break;
  1148.       default :
  1149.          break;
  1150.    }
  1151. }
  1152.  
  1153.  
  1154.  
  1155. processmenu(menu, item, subitem)
  1156. int   menu, item, subitem;
  1157. {
  1158.    switch(menu)
  1159.    {
  1160.       case PROJECT :
  1161.          switch (item)
  1162.          {
  1163.             case NEWGAME :
  1164.                whostarts = subitem + 1;
  1165.                initialize();
  1166.                break;
  1167.             case BOARDSIZE :
  1168.                if (numboxes != 6 + subitem * 2)
  1169.                   {
  1170.                   numboxes = 6 + subitem * 2;
  1171.                   initialize();
  1172.                   }
  1173.                break;
  1174.             case OPEN :
  1175.                loadgame();
  1176.                break;
  1177.             case SAVEGAME :
  1178.                savegame();
  1179.                break;
  1180.             case SAVEDEF :
  1181.                savedefaults();
  1182.                break;
  1183.             case ABOUT :
  1184.                info(menu,item,subitem);
  1185.                break;
  1186.             case HELP  :
  1187.                switch (subitem)
  1188.                   {
  1189.                   case FUNCTION :
  1190.                      helpfunction();
  1191.                      break;
  1192.                   case ALL :
  1193.                      info(menu,item,subitem);
  1194.                      break;
  1195.                   }
  1196.                break;
  1197.             case QUIT :
  1198.                ClearMenuStrip(window);
  1199.                ModifyIDCMP(window,NULL);
  1200.                if ( AutoRequest(window,&Quittext,&Postext,&Negtext,
  1201.                               NULL,NULL,180,57) )
  1202.                   {
  1203.                   SetMenuStrip(window,Titles);
  1204.                   quit_cleanup(0);
  1205.                   }
  1206.                ModifyIDCMP(window,IDCMPNORMAL);
  1207.                SetMenuStrip(window,Titles);
  1208.                break;
  1209.          }
  1210.          break;
  1211.       case PLAYER1 :
  1212.          looksp1 = item;
  1213.          break;
  1214.       case PLAYER2 :
  1215.          looksp2 = item;
  1216.          break;
  1217.       case GURUVSGURU :
  1218.          guruwait = item;
  1219.          break;
  1220.       case OTHER      :
  1221.          switch (item)
  1222.          {
  1223.             case MOVES :
  1224.                showmoves();
  1225.                break;
  1226.             case SUGGEST :
  1227.                suggest();
  1228.                break;
  1229.          }
  1230.          break;
  1231.    }
  1232. }
  1233.  
  1234.  
  1235.  
  1236. extern BOOL info_display();
  1237.  
  1238. helpfunction()
  1239. {
  1240.    struct IntuiMessage *message;
  1241.    ULONG MessageClass;
  1242.    USHORT WhichButton;
  1243.  
  1244.    ModifyIDCMP(window, MENUPICK);
  1245.  
  1246.    WaitPort(window->UserPort);
  1247.    message = (struct IntuiMessage *)GetMsg(window->UserPort);
  1248.    MessageClass = message->Class;
  1249.    WhichButton = message->Code;
  1250.    ReplyMsg(message);
  1251.    while (WhichButton != MENUNULL)
  1252.       {
  1253.       struct MenuItem *item;
  1254.       item = (struct MenuItem *)ItemAddress(Titles,WhichButton);
  1255.       if (info(MENUNUM(WhichButton),
  1256.                   ITEMNUM(WhichButton),
  1257.                   SUBNUM(WhichButton)) == FALSE)
  1258.          quit_cleanup("Info problem!!!\n");
  1259.       WhichButton = item->NextSelect;
  1260.       }
  1261.  
  1262.    ModifyIDCMP(window,IDCMPNORMAL);
  1263. }
  1264.  
  1265.  
  1266.  
  1267. info(menu,item,subitem)
  1268. int menu,item,subitem;
  1269. {
  1270.    ClearMenuStrip(window);
  1271.    ModifyIDCMP(window,NULL);
  1272.  
  1273.    info_display(menu,item,subitem);
  1274.  
  1275.    checkit();
  1276.    SetMenuStrip(window,Titles);
  1277.    ModifyIDCMP(window, IDCMPNORMAL);
  1278. }
  1279.  
  1280.  
  1281.  
  1282. showmoves()
  1283. {
  1284. short x, y;
  1285. BOOL  any = FALSE;
  1286.  
  1287.    showplayer(whoseturn, 141, 0);
  1288.    drawboard();
  1289.    for (x = 1; x <= numboxes; x++)
  1290.       for (y = 1; y <= numboxes; y++)
  1291.          if (move(x,y,whoseturn,MAXLOOK-1))
  1292.             {
  1293.             any = TRUE;
  1294.             highlight(x, y);
  1295.             }
  1296.    if (any)
  1297.       printstring(possible, 0, LINEHEIGHT);
  1298.    else
  1299.       printstring(youcant, 0, LINEHEIGHT);
  1300.    if (looksp1 != HUMAN && looksp2 != HUMAN && guruwait == RACETHROUGH)
  1301.       WaitPort(window->UserPort);
  1302. }
  1303.  
  1304.  
  1305.  
  1306. suggest()
  1307. {
  1308.    showplayer(whoseturn, 141, 0);
  1309.    if (moveable(whoseturn))
  1310.       {
  1311.       printstring(thinking, 0, LINEHEIGHT);
  1312.       think(2,whoseturn,MAXLOOK-1);
  1313.       drawboard();
  1314.       highlight(xthought, ythought);
  1315.       printstring(bestmove, 0, LINEHEIGHT);
  1316.       }
  1317.    else
  1318.       printstring(youcant, 0, LINEHEIGHT);
  1319.    if (looksp1 != HUMAN && looksp2 != HUMAN && guruwait == RACETHROUGH)
  1320.       WaitPort(window->UserPort);
  1321. }
  1322.  
  1323.  
  1324.  
  1325. highlight(x, y)
  1326. short x, y;
  1327. {
  1328.    smallsquare.FrontPen = whoseturn;
  1329.    x = xoffset + (x - 1) * boxwidth;
  1330.    y = yoffset + (y - 1) * boxheight;
  1331.    DrawBorder(window->RPort, &smallsquare, x, y);
  1332. }
  1333.  
  1334.  
  1335.  
  1336. checklooks(looks)
  1337. short looks;
  1338. {
  1339.    if (looks < LEVEL1 || looks > HUMAN)
  1340.       return(FALSE);
  1341.    else
  1342.       return(TRUE);
  1343. }
  1344.  
  1345.  
  1346.  
  1347. checksize(size)
  1348. short size;
  1349. {
  1350.    if (size != 6 && size != 8 && size != 10 && size != 12)
  1351.       return(FALSE);
  1352.    else
  1353.       return(TRUE);
  1354. }
  1355.  
  1356.  
  1357.  
  1358. checkguru(guru)
  1359. short guru;
  1360. {
  1361.    if (guru != STEPTHROUGH && guru != RACETHROUGH)
  1362.       return(FALSE);
  1363.    else
  1364.       return(TRUE);
  1365. }
  1366.  
  1367.  
  1368.  
  1369. checkwhose(whose)
  1370. short whose;
  1371. {
  1372.    if (whose != BLACK && whose != RED)
  1373.       return(FALSE);
  1374.    else
  1375.       return(TRUE);
  1376. }
  1377.  
  1378.  
  1379.  
  1380. loadgame()
  1381. {
  1382.    FILE *fp, *fopen();
  1383.    char *gamename, *getgamename();
  1384.    short x, y;
  1385.    short version, l_looksp1, l_looksp2, l_whoseturn, l_numboxes, l_guruwait;
  1386.    short l_scores[3];
  1387.    char  l_board[MAXBOXES][MAXBOXES];
  1388.    char  temp;
  1389.  
  1390.    gamename = getgamename();
  1391.  
  1392.    if ((fp = fopen(gamename, "r")) == NULL)
  1393.       {
  1394.       printstring(openfail, 0, LINEHEIGHT);
  1395.       return(FALSE);
  1396.       }
  1397.    if ((version = (short)(getc(fp))) == EOF)
  1398.       {
  1399.       printstring(shortfil, 0, LINEHEIGHT);
  1400.       fclose(fp);
  1401.       return(FALSE);
  1402.       }
  1403.    if ((l_looksp1 = (short)(getc(fp))) == EOF)
  1404.       {
  1405.       printstring(shortfil, 0, LINEHEIGHT);
  1406.       fclose(fp);
  1407.       return(FALSE);
  1408.       }
  1409.    if (!checklooks(l_looksp1))
  1410.       {
  1411.       printstring(illvalue, 0, LINEHEIGHT);
  1412.       fclose(fp);
  1413.       return(FALSE);
  1414.       }
  1415.    if ((l_looksp2 = (short)(getc(fp))) == EOF)
  1416.       {
  1417.       printstring(shortfil, 0, LINEHEIGHT);
  1418.       fclose(fp);
  1419.       return(FALSE);
  1420.       }
  1421.    if (!checklooks(l_looksp2))
  1422.       {
  1423.       printstring(illvalue, 0, LINEHEIGHT);
  1424.       fclose(fp);
  1425.       return(FALSE);
  1426.       }
  1427.    if ((l_numboxes = (short)(getc(fp))) == EOF)
  1428.       {
  1429.       printstring(shortfil, 0, LINEHEIGHT);
  1430.       fclose(fp);
  1431.       return(FALSE);
  1432.       }
  1433.    if (!checksize(l_numboxes))
  1434.       {
  1435.       printstring(illvalue, 0, LINEHEIGHT);
  1436.       fclose(fp);
  1437.       return(FALSE);
  1438.       }
  1439.    if ((l_guruwait = (short)(getc(fp))) == EOF)
  1440.       {
  1441.       printstring(shortfil, 0, LINEHEIGHT);
  1442.       fclose(fp);
  1443.       return(FALSE);
  1444.       }
  1445.    if (!checkguru(l_guruwait))
  1446.       {
  1447.       printstring(illvalue, 0, LINEHEIGHT);
  1448.       fclose(fp);
  1449.       return(FALSE);
  1450.       }
  1451.    l_scores[RED] = 0;
  1452.    l_scores[BLACK] = 0;
  1453.    if ((l_whoseturn = (short)(getc(fp))) == EOF)
  1454.       {
  1455.       printstring(shortfil, 0, LINEHEIGHT);
  1456.       fclose(fp);
  1457.       return(FALSE);
  1458.       }
  1459.    if (!checkwhose(l_whoseturn))
  1460.       {
  1461.       printstring(illvalue, 0, LINEHEIGHT);
  1462.       fclose(fp);
  1463.       return(FALSE);
  1464.       }
  1465.  
  1466.    for (x=1; x<=l_numboxes; x++)
  1467.       for (y=1; y<=l_numboxes; y++)
  1468.          {
  1469.          if ((temp = (short)(getc(fp))) == EOF)
  1470.             {
  1471.             printstring(shortfil, 0, LINEHEIGHT);
  1472.             fclose(fp);
  1473.             return(FALSE);
  1474.             }
  1475.          if (temp != EMPTY && temp != BLACK && temp != RED)
  1476.             {
  1477.             printstring(illvalue, 0, LINEHEIGHT);
  1478.             fclose(fp);
  1479.             return(FALSE);
  1480.             }
  1481.          l_board[x][y] = temp;
  1482.          l_scores[l_board[x][y]]++;
  1483.          }
  1484.  
  1485.    fclose(fp);
  1486.  
  1487.    looksp1 = l_looksp1;
  1488.    looksp2 = l_looksp2;
  1489.    whoseturn = l_whoseturn;
  1490.    guruwait = l_guruwait;
  1491.    numboxes = l_numboxes;
  1492.  
  1493.    initialize();
  1494.  
  1495.    for (x=1; x<=numboxes; x++)
  1496.       for (y=1; y<=numboxes; y++)
  1497.          {
  1498.          plot(x,y,l_board[x][y],NOBOXIT);
  1499.          }
  1500.  
  1501.    scores[RED] = l_scores[RED];
  1502.    scores[BLACK] = l_scores[BLACK];
  1503.  
  1504.    printscores();
  1505.    ClearMenuStrip(window);
  1506.    checkit();
  1507.    SetMenuStrip(window,Titles);
  1508.    printstring(loaded, 0, LINEHEIGHT);
  1509. }
  1510.  
  1511.  
  1512.  
  1513. savegame()
  1514. {
  1515.    FILE *fp, *fopen();
  1516.    char *gamename, *getgamename();
  1517.    short x, y;
  1518.  
  1519.    gamename = getgamename();
  1520.  
  1521.    if ((fp = fopen(gamename, "w")) == NULL)
  1522.       {
  1523.       printstring(openfail, 0, LINEHEIGHT);
  1524.       return(FALSE);
  1525.       }
  1526.    if (putc(VERSION,fp) == EOF)
  1527.       {
  1528.       printstring(writfail, 0, LINEHEIGHT);
  1529.       fclose(fp);
  1530.       return(FALSE);
  1531.       }
  1532.    if (putc((char)(looksp1),fp) == EOF)
  1533.       {
  1534.       printstring(writfail, 0, LINEHEIGHT);
  1535.       fclose(fp);
  1536.       return(FALSE);
  1537.       }
  1538.    if (putc((char)(looksp2),fp) == EOF)
  1539.       {
  1540.       printstring(writfail, 0, LINEHEIGHT);
  1541.       fclose(fp);
  1542.       return(FALSE);
  1543.       }
  1544.    if (putc((char)(numboxes),fp) == EOF)
  1545.       {
  1546.       printstring(writfail, 0, LINEHEIGHT);
  1547.       fclose(fp);
  1548.       return(FALSE);
  1549.       }
  1550.    if (putc((char)(guruwait),fp) == EOF)
  1551.       {
  1552.       printstring(writfail, 0, LINEHEIGHT);
  1553.       fclose(fp);
  1554.       return(FALSE);
  1555.       }
  1556.    if (putc((char)(whoseturn),fp) == EOF)
  1557.       {
  1558.       printstring(writfail, 0, LINEHEIGHT);
  1559.       fclose(fp);
  1560.       return(FALSE);
  1561.       }
  1562.    for (x=1; x <= numboxes; x++)
  1563.       for (y=1; y <= numboxes; y++)
  1564.          if (putc(game[MAXLOOK-1][x][y],fp) == EOF)
  1565.             {
  1566.             printstring(writfail, 0, LINEHEIGHT);
  1567.             fclose(fp);
  1568.             return(FALSE);
  1569.             }
  1570.    fclose(fp);
  1571.    printstring(saved, 0, LINEHEIGHT);
  1572.    return(TRUE);
  1573. }
  1574.  
  1575.  
  1576.  
  1577. char *getgamename()
  1578. {
  1579.    return("Othello.sav");
  1580. }
  1581.  
  1582.  
  1583.  
  1584. savedefaults()
  1585. {
  1586.    FILE *fp, *fopen();
  1587.  
  1588.    if ((fp = fopen( DISKDEFNAME, "w")) == NULL)
  1589.       {
  1590.       printstring(openfail, 0, LINEHEIGHT);
  1591.       return(FALSE);
  1592.       }
  1593.    if (putc(VERSION,fp) == EOF)
  1594.       {
  1595.       printstring(writfail, 0, LINEHEIGHT);
  1596.       fclose(fp);
  1597.       return(FALSE);
  1598.       }
  1599.    if (putc((char)(looksp1),fp) == EOF)
  1600.       {
  1601.       printstring(writfail, 0, LINEHEIGHT);
  1602.       fclose(fp);
  1603.       return(FALSE);
  1604.       }
  1605.    if (putc((char)(looksp2),fp) == EOF)
  1606.       {
  1607.       printstring(writfail, 0, LINEHEIGHT);
  1608.       fclose(fp);
  1609.       return(FALSE);
  1610.       }
  1611.    if (putc((char)(numboxes),fp) == EOF)
  1612.       {
  1613.       printstring(writfail, 0, LINEHEIGHT);
  1614.       fclose(fp);
  1615.       return(FALSE);
  1616.       }
  1617.    if (putc((char)(guruwait),fp) == EOF)
  1618.       {
  1619.       printstring(writfail, 0, LINEHEIGHT);
  1620.       fclose(fp);
  1621.       return(FALSE);
  1622.       }
  1623.    fclose(fp);
  1624.    printstring(defsaved, 0, LINEHEIGHT);
  1625.    return(TRUE);
  1626. }
  1627.  
  1628.  
  1629.  
  1630. checkit()
  1631. {
  1632. short ordinal, x;
  1633.  
  1634.    ordinal  = 1 + STARTP2;
  1635.    for (x = 0; x <= SQUARE12; x++)
  1636.       SubItems[ordinal+x].Flags                 &= ~CHECKED;
  1637.    SubItems[ordinal + ((numboxes-6)/2)].Flags   |= CHECKED;
  1638.  
  1639.    ordinal  = 1 + QUIT;
  1640.    for (x = 0; x <= HUMAN; x++)
  1641.       Items[ordinal+x].Flags                    &= ~CHECKED;
  1642.    Items[ordinal+looksp1].Flags                 |= CHECKED;
  1643.  
  1644.    ordinal += 1 + HUMAN;
  1645.    for (x = 0; x <= HUMAN; x++)
  1646.       Items[ordinal+x].Flags                    &= ~CHECKED;
  1647.    Items[ordinal+looksp2].Flags                 |= CHECKED;
  1648.  
  1649.    ordinal += 1 + HUMAN;
  1650.    for (x = 0; x <= RACETHROUGH; x++)
  1651.       Items[ordinal+x].Flags                    &= ~CHECKED;
  1652.    Items[ordinal+guruwait].Flags                |= CHECKED;
  1653. }
  1654.  
  1655.  
  1656.  
  1657. getdefaults()
  1658. {
  1659.    looksp1  = DEFAULTP1;
  1660.    looksp2  = DEFAULTP2;
  1661.    numboxes = DEFAULTSIZE;
  1662.    guruwait = DEFAULTGURUWAIT;
  1663.  
  1664.    getdiskdefaults();
  1665.    checkit();
  1666. }
  1667.  
  1668.  
  1669.  
  1670. getdiskdefaults()
  1671. {
  1672.    FILE *fp, *fopen();
  1673.    short version, l_looksp1, l_looksp2, l_numboxes, l_guruwait;
  1674.  
  1675.    if ((fp = fopen( DISKDEFNAME, "r" )) == NULL)
  1676.       return(0);
  1677.    if ((version = (short)(getc(fp))) == EOF)
  1678.       {
  1679.       printstring(shortfil, 0, LINEHEIGHT);
  1680.       return(FALSE);
  1681.       }
  1682.    if ((l_looksp1 = (short)(getc(fp))) == EOF)
  1683.       {
  1684.       printstring(shortfil, 0, LINEHEIGHT);
  1685.       return(FALSE);
  1686.       }
  1687.    if (!checklooks(l_looksp1))
  1688.       {
  1689.       printstring(illvalue, 0, LINEHEIGHT);
  1690.       return(FALSE);
  1691.       }
  1692.    if ((l_looksp2 = (short)(getc(fp))) == EOF)
  1693.       {
  1694.       printstring(shortfil, 0, LINEHEIGHT);
  1695.       return(FALSE);
  1696.       }
  1697.    if (!checklooks(l_looksp2))
  1698.       {
  1699.       printstring(illvalue, 0, LINEHEIGHT);
  1700.       return(FALSE);
  1701.       }
  1702.    if ((l_numboxes = (short)(getc(fp))) == EOF)
  1703.       {
  1704.       printstring(shortfil, 0, LINEHEIGHT);
  1705.       return(FALSE);
  1706.       }
  1707.    if (!checksize(l_numboxes))
  1708.       {
  1709.       printstring(illvalue, 0, LINEHEIGHT);
  1710.       return(FALSE);
  1711.       }
  1712.    if ((l_guruwait = (short)(getc(fp))) == EOF)
  1713.       {
  1714.       printstring(shortfil, 0, LINEHEIGHT);
  1715.       return(FALSE);
  1716.       }
  1717.    if (!checkguru(l_guruwait))
  1718.       {
  1719.       printstring(illvalue, 0, LINEHEIGHT);
  1720.       return(FALSE);
  1721.       }
  1722.    fclose(fp);
  1723.    looksp1 = l_looksp1;
  1724.    looksp2 = l_looksp2;
  1725.    numboxes = l_numboxes;
  1726.    guruwait = l_guruwait;
  1727.    return(0);
  1728. }
  1729.  
  1730.  
  1731.  
  1732. clearport()
  1733. {
  1734.    struct IntuiMessage *message;
  1735.  
  1736.    while (message = (struct IntuiMessage *)GetMsg(window->UserPort))
  1737.    {
  1738.       if (message->Class == MOUSEBUTTONS)
  1739.          ReplyMsg(message);
  1740.       else
  1741.          processmessage(message);
  1742.    }
  1743. }
  1744.  
  1745.  
  1746.  
  1747. quit_cleanup(x)
  1748. char *x;
  1749. {
  1750.    if (circle)
  1751.       FreeRaster(circle,WIDE,HIGH);
  1752.    if (ourpointer)
  1753.       FreeRaster(ourpointer,POINTERWIDTH*2,POINTERHEIGHT*2);
  1754.    if (window)
  1755.    {
  1756.       ClearMenuStrip(window);
  1757.       CloseWindow(window);
  1758.    }
  1759.    if (GfxBase)
  1760.       CloseLibrary(GfxBase);
  1761.    if (IntuitionBase)
  1762.       CloseLibrary(IntuitionBase);
  1763.    if (!(workbench) && x)
  1764.       printf("%s\n",x);
  1765.    exit(0);
  1766. }
  1767.  
  1768.  
  1769.  
  1770. drawboard()
  1771. {
  1772.    short i;
  1773.  
  1774.    for (i = 1; i < numboxes; i++)
  1775.    {
  1776.       DrawBorder(window->RPort,&xline,xoffset,yoffset+i*boxheight);
  1777.       DrawBorder(window->RPort,&yline,xoffset+i*boxwidth,yoffset);
  1778.    }
  1779.    DrawBorder(window->RPort, &square, xoffset, yoffset);
  1780. }
  1781.  
  1782.  
  1783.  
  1784. initialize()
  1785. {
  1786. short x, y, r;
  1787.  
  1788.    newgame = TRUE;
  1789.  
  1790.    printstring(blank, 0, LINEHEIGHT);
  1791.  
  1792.    whoseturn = whostarts;
  1793.  
  1794.    boxheight = height / numboxes;
  1795.    boxwidth = width / numboxes;
  1796.  
  1797.    r = (boxheight - 2) / 2;
  1798.    player.Width = r * 4;
  1799.    player.Height = r * 2;
  1800.    generatecircle(r, circle + (r - 1) * 256);
  1801.    player.ImageData = (short *)&circle[256 * (r - 1)];
  1802.  
  1803.    stuck = FALSE;
  1804.  
  1805.    for (r = 0; r <= MAXLOOK-1; r++)
  1806.       for (x = 0; x <= numboxes + 1; x++)
  1807.          for (y = 0; y <= numboxes + 1; y++)
  1808.             game[r][x][y] = OFFSCREEN;
  1809.  
  1810.    for (x = 1; x <= numboxes; x++)
  1811.       for (y = 1; y <= numboxes; y++)
  1812.          game[MAXLOOK-1][x][y] = EMPTY;
  1813.  
  1814.    squarepoints[0] = squarepoints[1] = 0;
  1815.    squarepoints[2] = squarepoints[4] = numboxes * boxwidth;
  1816.    squarepoints[5] = squarepoints[7] = numboxes * boxheight;
  1817.    squarepoints[3] = squarepoints[6] = 0;
  1818.    squarepoints[8] = squarepoints[9] = 0;
  1819.  
  1820.    smallsquarepoints[0] = smallsquarepoints[1] = 0;
  1821.    smallsquarepoints[2] = smallsquarepoints[4] = boxwidth;
  1822.    smallsquarepoints[5] = smallsquarepoints[7] = boxheight;
  1823.    smallsquarepoints[3] = smallsquarepoints[6] = 0;
  1824.    smallsquarepoints[8] = smallsquarepoints[9] = 0;
  1825.  
  1826.    SetAPen(window->RPort, 0);
  1827.    RectFill(window->RPort,xoffset,yoffset,xoffset+width+1,yoffset+height+1);
  1828.  
  1829.    drawboard();
  1830.  
  1831.    game[MAXLOOK-1][numboxes/2][numboxes/2] = RED;
  1832.    game[MAXLOOK-1][numboxes/2+1][numboxes/2+1] = RED;
  1833.    game[MAXLOOK-1][numboxes/2+1][numboxes/2] = BLACK;
  1834.    game[MAXLOOK-1][numboxes/2][numboxes/2+1] = BLACK;
  1835.  
  1836.    scores[RED] = 2;
  1837.    scores[BLACK] = 2;
  1838.    printscores();
  1839.  
  1840.    plot(numboxes/2,numboxes/2,RED,NOBOXIT);
  1841.    plot(numboxes/2+1,numboxes/2+1,RED,NOBOXIT);
  1842.    plot(numboxes/2+1,numboxes/2,BLACK,NOBOXIT);
  1843.    plot(numboxes/2,numboxes/2+1,BLACK,NOBOXIT);
  1844.  
  1845.    printstring(yourmove, 0, 0);
  1846.  
  1847.    for (x = 0; x < numboxes+2; x++)
  1848.       for (y = 0; y < numboxes+2; y++)
  1849.          bonus[x][y] = 0;
  1850.    for (x = 1; x < numboxes+1; x++)
  1851.       for (y = 1; y < numboxes+1; y++)
  1852.          bonus[x][y] = 3;
  1853.    for (x = 2; x < numboxes; x++)
  1854.       for (y = 2; y < numboxes; y++)
  1855.          bonus[x][y] = -1;
  1856.    for (x = 3; x < numboxes-1; x++)
  1857.       for (y = 3; y < numboxes-1; y++)
  1858.          bonus[x][y] = 0;
  1859.  
  1860.    bonus[1][1] = bonus[numboxes][1] = 13;
  1861.    bonus[numboxes][numboxes] = bonus[1][numboxes] = 13;
  1862.  
  1863.    bonus[2][2] = bonus[numboxes-1][2] = -9;
  1864.    bonus[numboxes-1][numboxes-1] = bonus[2][numboxes-1] = -9;
  1865.  
  1866.    bonus[2][1] = bonus[numboxes-1][1] = -2;
  1867.    bonus[1][2] = bonus[numboxes][2] = -2;
  1868.  
  1869.    bonus[numboxes][numboxes-1] = bonus[1][numboxes-1] = -2;
  1870.    bonus[numboxes-1][numboxes] = bonus[2][numboxes] = -2;
  1871.  
  1872.  
  1873. /* This is what the original bonus array looked like for an 8 by 8 game
  1874.    board.
  1875. {  {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0  },
  1876.    {  0, 13, -2,  3,  3,  3,  3, -2, 13,  0  },
  1877.    {  0, -2, -9, -1, -1, -1, -1, -9, -2,  0  },
  1878.    {  0,  3, -1,  0,  0,  0,  0, -1,  3,  0  },
  1879.    {  0,  3, -1,  0,  0,  0,  0, -1,  3,  0  },
  1880.    {  0,  3, -1,  0,  0,  0,  0, -1,  3,  0  },
  1881.    {  0,  3, -1,  0,  0,  0,  0, -1,  3,  0  },
  1882.    {  0, -2, -9, -1, -1, -1, -1, -9, -2,  0  },
  1883.    {  0, 13, -2,  3,  3,  3,  3, -2, 13,  0  },
  1884.    {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0  }
  1885. };   */
  1886.    /* Add a large enough number to make all the bonus value positive. */
  1887.  
  1888.    for (x = 1; x < numboxes+1; x++)
  1889.       for (y = 1; y < numboxes+1; y++)
  1890.          bonus[x][y] += 9;
  1891.  
  1892. }
  1893.